#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#      This file is distributed as part of the WebAMP2 project and is licensed
#      under the GPL version 3.
#
#      Copyright 2007 Chris Seickel <cseickel@gmail.com>
#
#      This program is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License version 3 as 
#      published by the Free Software Foundation.
#
#      This program is distributed in the hope that it will be useful,
#      but WITHOUT ANY WARRANTY; without even the implied warranty of
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#      GNU General Public License version 3 for more details.
#
#      You should have received a copy of the GNU General Public License
#      along with this program; if not, write to:
#       Free Software Foundation, Inc.
#       51 Franklin Street, Fifth Floor
#       Boston, MA 02110-1301, USA


from datetime import datetime

import socket
from threading import Thread
from time import sleep

class Client:
    def __init__(self, host, port, init=[]):
        self.host = host
        self.port = port
        self.pending = init
        self.delayed = []
        self.errors = []
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((host, port))
        
        
class JS_SocketController(Thread):
    def __init__(self, onConnect=None):
        self.clients = []
        self.onConnect = onConnect
        self._active = True
        Thread.__init__(self, name="WebAMP2_ClientThread")
        self.start()
            
    def connect(self, host, port, init=""):
        for c in self.clients:
            if c.host == host and c.port == port:
                return False
        client = Client(host, port, [init])
        self.clients.append(client)
        self.onConnect(client)
        return True
                                
    def disconnect(self, host, port):
        for c in self.clients:
            if c.host == host and c.port == port:
                c.sock.close()
                self.clients.remove(c)
            
    def push(self, msg, client=None):
        if (client == None):
            clients = self.clients
        else:
            clients = [client]  
        for item in clients:
            item.pending.append(msg)
    
    def stop(self):
        self._active = False
        for c in self.clients:
            c.sock.close()
            
    def run(self):
        self._active = True
        while self._active:
            for c in self.clients:
                if len(c.pending) > 0:
                    msg = u';'.join(c.pending)
                    c.pending = []
                    try:
                        print "Sending message: "+msg
                        c.sock.send("START::"+msg+"::END")
                    except:
                        c.sock.close()
                        self.clients.remove(c)
                    
                        

class JSController:
    def __init__(self, slots=dict(root=[]), onConnect=None):
        self.slots = slots
        self.clientCount = 0
        self.queue = dict()
        self.onConnect = onConnect
        
    def addClient(self, cid, slots=["root"], init=[]):
        if self.queue.has_key(cid):
            self.disconnect(cid, slot="all")
        self.queue[cid]=dict(script=init)
        #Every client is connected to root, other slot connections are optional
        self.connect(cid, slots)
        self.clientCount += 1
        return cid
    
    def addSlot(self, slot):
        if not self.slots.has_key(slot):
            self.slots[slot] = []
    
    def connect(self, client, slots=["root"]):
        for slot in slots:
            if (self.slots[slot].count(client) == 0):
                self.slots[slot].append(client)
            else:
                self.queue[client]["script"] = []
            self.onConnect(client, slot)
            self.addSlot(slot)
                                
        
    def disconnect(self, client, slot="all"):
        if (slot == "all"): slots=self.slots
        else: slots = [slot]
        for slot in slots:
            if (self.slots[slot].count(client) > 0):
                self.slots[slot].remove(client)
        if self.queue.has_key(client): del self.queue[client]
    
    def clear(self, client):
        # Remove all pending items for this client
        self.queue[client]["script"] = []
            
    def push(self, script, slot="root", client=None):
        print "enqueing script: "+script
        if (client == None):
            self.addSlot(slot)
            clients = self.slots[slot]
        else:
            clients = [client]
            
        for item in clients:
            self.queue[item]["script"].append(script)
        
    def nextInQueue(self, client):
        js = ""
        if (len(self.queue[client]["script"]) > 0):
            js = ";".join(self.queue[client]["script"])
            self.queue[client]["script"] = []
        return js

                
